<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.7.1">
<meta name="author" content="Advanced Micro Devices - Version 1.1.0, 2018-08-25">
<title>V-EZ API Documentation</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Uncomment @import statement below to use as custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
audio,canvas,video{display:inline-block}
audio:not([controls]){display:none;height:0}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
a{background:transparent}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:none}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite::before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
.clearfix::after,.float-group::after{clear:both}
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
*:not(pre)>code.nobreak{word-wrap:normal}
*:not(pre)>code.nowrap{white-space:nowrap}
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:"[";padding:0 3px 0 2px}
b.button::after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:"\00a0\2013\00a0"}
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #efefed}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.listingblock>.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999}
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
table.pyhltable td.code{padding-left:.75em;padding-right:0}
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
pre.pygments .lineno{display:inline-block;margin-right:.25em}
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
.quoteblock .quoteblock blockquote::before{display:none}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{word-spacing:0;line-height:1.6}
.quoteblock.abstract blockquote::before,.quoteblock.abstract p::before{display:none}
table.tableblock{max-width:100%;border-collapse:separate}
p.tableblock:last-child{margin-bottom:0}
td.tableblock>.content{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot,table.frame-ends{border-width:1px 0}
table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7}
table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
td>div.verse{white-space:pre}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline>li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
span.icon>.fa{cursor:default}
a span.icon>.fa{cursor:inherit}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]::after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
</style>
<style>
/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
/*pre.CodeRay {background-color:#f7f7f8;}*/
.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
table.CodeRay td{vertical-align: top;line-height:1.45}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
table.CodeRay td.code{padding:0 0 0 .5em}
table.CodeRay td.code>pre{padding:0}
.CodeRay .debug{color:#fff !important;background:#000080 !important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:#000080}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:#008080}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:#008080}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:#008080}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
</style>
<style>code { font-size: 0.8em } #header, #content, #footer, #footnotes { max-width: 90% }</style>
</head>
<body class="book toc2 toc-left" style="max-width: 90;">
<div id="header">
<h1>V-EZ API Documentation</h1>
<div class="details">
<span id="author" class="author">Advanced Micro Devices - Version 1.1.0, 2018-08-25</span><br>
</div>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_introduction">1. Introduction</a>
<ul class="sectlevel2">
<li><a href="#_what_is_v_ez">1.1. What is V-EZ?</a></li>
<li><a href="#_what_is_abstracted_from_vulkan">1.2. What is Abstracted From Vulkan?</a></li>
<li><a href="#_performance_comparisons">1.3. Performance Comparisons</a></li>
<li><a href="#_native_vulkan_calls">1.4. Native Vulkan Calls</a></li>
</ul>
</li>
<li><a href="#_initialization">2. Initialization</a>
<ul class="sectlevel2">
<li><a href="#_instances">2.1. Instances</a></li>
<li><a href="#_surfaces">2.2. Surfaces</a></li>
<li><a href="#_physical_devices">2.3. Physical Devices</a>
<ul class="sectlevel3">
<li><a href="#_extensions_support">2.3.1. Extensions Support</a></li>
<li><a href="#_layers_support">2.3.2. Layers Support</a></li>
</ul>
</li>
<li><a href="#_devices">2.4. Devices</a></li>
<li><a href="#_swapchains_and_present_support">2.5. Swapchains and Present Support</a></li>
<li><a href="#_putting_it_all_together">2.6. Putting It All Together</a></li>
</ul>
</li>
<li><a href="#_queues">3. Queues</a>
<ul class="sectlevel2">
<li><a href="#_queue_families">3.1. Queue Families</a></li>
<li><a href="#_queue_submission">3.2. Queue Submission</a></li>
<li><a href="#_queue_presentation">3.3. Queue Presentation</a>
<ul class="sectlevel3">
<li><a href="#_multisampled_images">3.3.1. Multisampled Images</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#_synchronization">4. Synchronization</a>
<ul class="sectlevel2">
<li><a href="#_fences">4.1. Fences</a></li>
<li><a href="#_semaphores">4.2. Semaphores</a></li>
<li><a href="#_events">4.3. Events</a></li>
<li><a href="#_wait_idle_operations">4.4. Wait Idle Operations</a></li>
</ul>
</li>
<li><a href="#_pipelines">5. Pipelines</a>
<ul class="sectlevel2">
<li><a href="#_shader_modules">5.1. Shader Modules</a></li>
<li><a href="#_graphics_pipelines">5.2. Graphics Pipelines</a></li>
<li><a href="#_compute_pipelines">5.3. Compute Pipelines</a></li>
<li><a href="#_specialization_constants">5.4. Specialization Constants</a></li>
<li><a href="#_push_constants">5.5. Push Constants</a></li>
<li><a href="#_pipeline_reflection">5.6. Pipeline Reflection</a></li>
<li><a href="#_pipeline_binding">5.7. Pipeline Binding</a></li>
</ul>
</li>
<li><a href="#_vertex_input_formats">6. Vertex Input Formats</a>
<ul class="sectlevel2">
<li><a href="#_creation">6.1. Creation</a></li>
<li><a href="#_destruction">6.2. Destruction</a></li>
</ul>
</li>
<li><a href="#_resource_creation">7. Resource Creation</a>
<ul class="sectlevel2">
<li><a href="#_buffers">7.1. Buffers</a></li>
<li><a href="#_buffer_views">7.2. Buffer Views</a></li>
<li><a href="#_images">7.3. Images</a></li>
<li><a href="#_image_views">7.4. Image Views</a></li>
<li><a href="#_framebuffers">7.5. Framebuffers</a>
<ul class="sectlevel3">
<li><a href="#_multisampled_framebuffers">7.5.1. Multisampled Framebuffers</a></li>
<li><a href="#_framebuffers_with_no_attachments">7.5.2. Framebuffers With No Attachments</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#_samplers">8. Samplers</a></li>
<li><a href="#_command_buffers">9. Command Buffers</a>
<ul class="sectlevel2">
<li><a href="#_allocation_and_management">9.1. Allocation and Management</a></li>
<li><a href="#_recording">9.2. Recording</a></li>
<li><a href="#_graphics_state">9.3. Graphics State</a></li>
<li><a href="#_resource_binding">9.4. Resource Binding</a></li>
</ul>
</li>
<li><a href="#_render_passes">10. Render Passes</a>
<ul class="sectlevel2">
<li><a href="#_begin_a_render_pass">10.1. Begin A Render Pass</a></li>
<li><a href="#_next_subpass">10.2. Next Subpass</a></li>
<li><a href="#_end_a_render_pass">10.3. End A Render Pass</a></li>
<li><a href="#_input_attachments">10.4. Input Attachments</a></li>
</ul>
</li>
<li><a href="#_updating_memory">11. Updating Memory</a>
<ul class="sectlevel2">
<li><a href="#_map_and_unmap">11.1. Map and Unmap</a></li>
<li><a href="#_utility_functions">11.2. Utility Functions</a></li>
</ul>
</li>
<li><a href="#_glsl_guide">12. GLSL Guide</a></li>
</ul>
</div>
</div>
<div id="content">
<div class="sect1">
<h2 id="_introduction">1. Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This document describes the V-EZ Vulkan wrapper library, what it is, what it abstracts away from the Vulkan API, and how to use it. Comparisons to Vulkan are made with the assumption the reader has a moderate understanding of the Khronos specification. In many sections of this documentation, details of functions calls are omitted since the behavior is nearly identical to Vulkan. The latest specification for the Vulkan API can be found <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html">here</a>.</p>
</div>
<div class="sect2">
<h3 id="_what_is_v_ez">1.1. What is V-EZ?</h3>
<div class="paragraph">
<p>V-EZ is designed to be a C based light-weight layer around Vulkan which maintains mostly identical semantics but abstracts away the lower level complexities. The motivation behind this design is to accelerate adoption of Vulkan among software vendors outside of the gaming industry, who desire modern graphics API features without all of the low level responsibilities.</p>
</div>
</div>
<div class="sect2">
<h3 id="_what_is_abstracted_from_vulkan">1.2. What is Abstracted From Vulkan?</h3>
<div class="paragraph">
<p>The following is a short list of low level Vulkan API features and responsibilities which are abstracted in V-EZ and no longer a concern of the application.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Memory management</p>
</li>
<li>
<p>Swapchain management</p>
</li>
<li>
<p>Render Passes</p>
</li>
<li>
<p>Pipeline permutations</p>
</li>
<li>
<p>Pipeline layouts</p>
</li>
<li>
<p>Pipeline barriers</p>
</li>
<li>
<p>Descriptor pools</p>
</li>
<li>
<p>Descriptor sets</p>
</li>
<li>
<p>Descriptor set layouts</p>
</li>
<li>
<p>Image layouts</p>
</li>
<li>
<p>GLSL compilation</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Below is a diagram of the Vulkan API objects and their interactions.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./img/VulkanAPI.PNG" alt="Vulkan API Objects">
</div>
</div>
<div class="paragraph">
<p>The next image is a diagram of V-EZ.  Notice the number of native Vulkan objects which are abstracted and whose responsibility is removed from the application.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./img/V-EZ.PNG" alt="V-EZ API">
</div>
</div>
</div>
<div class="sect2">
<h3 id="_performance_comparisons">1.3. Performance Comparisons</h3>
<div class="paragraph">
<p>V-EZ incurs only slight overhead compared to native Vulkan API calls. However in most cases the performance overhead is negligible.  Existing best practices with respect to Vulkan are still applicable with V-EZ.  These include, but are not limited to:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Batching queue submissions</p>
</li>
<li>
<p>Multi-threaded command buffer recording</p>
</li>
<li>
<p>Reusing command buffers</p>
</li>
<li>
<p>Minimizing pipeline bindings</p>
</li>
<li>
<p>Minimizing resource bindings</p>
</li>
<li>
<p>Batching draw calls</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_native_vulkan_calls">1.4. Native Vulkan Calls</h3>
<div class="paragraph">
<p>Most object handles created by V-EZ are the native Vulkan objects.  These can be used in native Vulkan.  There are only a few exceptions, which are prefixed with <code>vez</code> rather than <code>vk</code>.  These object handles may only be passed to V-EZ.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>vezSwapchain</p>
</li>
<li>
<p>vezCommandBuffer</p>
</li>
<li>
<p>vezPipeline</p>
</li>
<li>
<p>vezFramebuffer</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Any native Vulkan API functions that do not exist within V-EZ may be used with Vulkan object handles returned by V-EZ.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_initialization">2. Initialization</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This section describes how an application initializes V-EZ, enumerates devices attached to the system and creates one or more handles to those devices for use.</p>
</div>
<div class="sect2">
<h3 id="_instances">2.1. Instances</h3>
<div class="paragraph">
<p>The first step to using V-EZ is to create a <code>VkInstance</code> object by calling <code>vezCreateInstance</code> with appropriate parameter values set in <code>VezInstanceCreateInfo</code> and <code>VezApplicationInfo</code>. These structures allow an application to pass information about itself to V-EZ. Below is a simple example call.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span>VezApplicationInfo appInfo = {};
<span class="line-numbers"> 2</span>appInfo.pApplicationName = <span class="string"><span class="delimiter">&quot;</span><span class="content">MyApplication</span><span class="delimiter">&quot;</span></span>;
<span class="line-numbers"> 3</span>appInfo.applicationVersion = VK_MAKE_VERSION(<span class="integer">1</span>, <span class="integer">0</span>, <span class="integer">0</span>);
<span class="line-numbers"> 4</span>appInfo.pEngineName = <span class="string"><span class="delimiter">&quot;</span><span class="content">MyEngine</span><span class="delimiter">&quot;</span></span>;
<span class="line-numbers"> 5</span>appinfo.engineVersion = VK_MAKE_VERSION(<span class="integer">1</span>, <span class="integer">0</span>, <span class="integer">0</span>);
<span class="line-numbers"> 6</span>
<span class="line-numbers"> 7</span>VezInstanceCreateInfo createInfo = {};
<span class="line-numbers"> 8</span>createInfo.pApplicationInfo = &amp;appInfo;
<span class="line-numbers"> 9</span>
<span class="line-numbers">10</span>VkInstance instance = VK_NULL_HANDLE;
<span class="line-numbers">11</span>VkResult result = vezCreateInstance(&amp;createInfo, &amp;instance);</code></pre>
</div>
</div>
<div class="paragraph">
<p>As with Vulkan, instance layers and extensions can be enabled by passing the relevant string names to <code>VezInstanceCreateInfo::ppEnabledLayerNames</code> and <code>VezInstanceCreateInfo::ppEnabledExtensionNames</code>. For example, to enable the LunarG standard validation layer, the above code would be modified to be the following below.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">1</span>std::array&lt;<span class="directive">const</span> <span class="predefined-type">char</span>*&gt; enabledLayers = { <span class="string"><span class="delimiter">&quot;</span><span class="content">VK_LAYER_LUNARG_standard_validation</span><span class="delimiter">&quot;</span></span> };
<span class="line-numbers">2</span>
<span class="line-numbers">3</span>VezInstanceCreateInfo createInfo = {};
<span class="line-numbers">4</span>createInfo.pApplicationInfo = &amp;appInfo;
<span class="line-numbers">5</span>createInfo.enabledLayerCount = <span class="keyword">static_cast</span>&lt;uint32_t&gt;(enabledLayers.size());
<span class="line-numbers">6</span>createInfo.ppEnabledLayerNames = enabledLayers.data();</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>vezEnumerateInstanceExtensionProperties</code> and <code>vezEnumerateInstanceLayerProperties</code> may be used to enumerate available instance extensions and layers.  The behavior is identical to native Vulkan. For more information about vkCreateInstance and instance layers and extensions, see the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#initialization-instances">Vulkan spec</a>.</p>
</div>
<div class="paragraph">
<p>A <code>VkInstance</code> object is destroyed by calling <code>VezDestroyInstance</code> when an application terminates.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">1</span>vezDestroyInstance(instance);</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_surfaces">2.2. Surfaces</h3>
<div class="paragraph">
<p>V-EZ does not abstract or wrap creation of surfaces in Vulkan.  Applications must use the platform specific WSI Vulkan extensions to create the surface. See the <a href="https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/html/vkspec.html#wsi">Vulkan spec</a> for details.</p>
</div>
</div>
<div class="sect2">
<h3 id="_physical_devices">2.3. Physical Devices</h3>
<div class="paragraph">
<p>To retrieve a list of physical devices in the system, call <code>vezEnumeratePhysicalDevices</code>, which behaves identically to its counterpart in Vulkan. Physical device properties and features can be retrieved via <code>vezGetPhysicalDeviceProperties</code> and <code>vezGetPhysicalDeviceFeatures</code>. The following code snippet demonstrates enumerating all available physical devices in a system and their properties and features.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span>uint32_t physicalDeviceCount;
<span class="line-numbers"> 2</span>vezEnumeratePhysicalDevices(instance, &amp;physicalDeviceCount, <span class="predefined-constant">nullptr</span>);
<span class="line-numbers"> 3</span>
<span class="line-numbers"> 4</span>std::vector&lt;VkPhysicalDevice&gt; physicalDevices(physicalDeviceCount);
<span class="line-numbers"> 5</span>vezEnumeratePhysicalDevices(instance, &amp;physicalDeviceCount, physicalDevices.data());
<span class="line-numbers"> 6</span>
<span class="line-numbers"> 7</span><span class="keyword">for</span> (<span class="directive">auto</span> physicalDevice : physicalDevices)
<span class="line-numbers"> 8</span>{
<span class="line-numbers"> 9</span>    VkPhysicalDeviceProperties properties;
<span class="line-numbers">10</span>    vezGetPhysicalDeviceProperties(physicalDevice, &amp;properties);
<span class="line-numbers">11</span>
<span class="line-numbers">12</span>    VkPhysicalDeviceFeatures features;
<span class="line-numbers">13</span>    vezGetPhysicalDeviceFeatures(physicalDevice, &amp;features);
<span class="line-numbers">14</span>}</code></pre>
</div>
</div>
<div class="sect3">
<h4 id="_extensions_support">2.3.1. Extensions Support</h4>
<div class="paragraph">
<p>All available Vulkan extensions for a physical device may be enumerated by calling <code>vezEnumerateDeviceExtensionProperties</code>. Each <code>VkExtensionProperties</code> entry in the output array will contain the string name of the supported extension. If an application needs to quickly check for the existence of a specific extension, it can call <code>vezGetPhysicalDeviceExtensionSupport</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="_layers_support">2.3.2. Layers Support</h4>
<div class="paragraph">
<p>As with physical device specific extensions, layers can be enumerated with <code>vezEnumerateDeviceLayerProperties</code>.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_devices">2.4. Devices</h3>
<div class="paragraph">
<p>Device objects represent logical connections to physical devices (see the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#devsandqueues-devices">Vulkan spec</a>). An application must create separate device object handles for each physical device it will use.  <code>vezCreateDevice</code> is used to create a logical connection to a physical device.</p>
</div>
<div class="paragraph">
<p>An application may specify a list of device level extensions to enable (see the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#extended-functionality-extensions">Vulkan spec</a>) by populating <code>vezCreateDeviceInfo::ppEnabledExtensionNames</code>.  Device level layers can be enabled by populating <code>vezCreateDeviceInfo::ppEnabledLayerNames</code>.  The code snippet below demonstrates creating a device with the <code>VK_KHR_swapchain</code> extension enabled.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">1</span>std::array&lt;<span class="directive">const</span> <span class="predefined-type">char</span>*, <span class="integer">1</span>&gt; enabledExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
<span class="line-numbers">2</span>
<span class="line-numbers">3</span>VezDeviceCreateInfo deviceCreateInfo = {};
<span class="line-numbers">4</span>deviceCreateInfo.enabledExtensionCount = <span class="keyword">static_cast</span>&lt;uint32_t&gt;(enabledExtensions.size());
<span class="line-numbers">5</span>deviceCreateInfo.ppEnabledExtensionNames = enabledExtensions.data();
<span class="line-numbers">6</span>
<span class="line-numbers">7</span>VkDevice device = VK_NULL_HANDLE;
<span class="line-numbers">8</span>VkResult result = vezCreateDevice(physicalDevice, &amp;deviceCreateInfo, &amp;device);</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_swapchains_and_present_support">2.5. Swapchains and Present Support</h3>
<div class="paragraph">
<p>To determine if a physical device supports a particular surface format, call <code>vezGetPhysicalDeviceSurfaceFormats</code>. This will retrieve an array of <code>VkFormat</code> and <code>VkColorSpace</code> values which can be used to check for required compatibility, for example HDR10. In some cases a surface attached to a window handle may not support being presented to, or may only support present with a specific queue family index (see <a href="#_queues">Queues</a>). This can be determined by calling <code>vezGetPhysicalDevicePresentSupport</code>.</p>
</div>
<div class="paragraph">
<p>After enumerating supported image formats and color spaces for a given physical device, an application can create one or more swapchains in V-EZ by calling <code>vezCreateSwapchain</code> with appropriate parameters for <code>VezSwapchainCreateInfo</code>. In contrast to Vulkan, V-EZ manages most of the responsibilities of an application&#8217;s swapchain.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">1</span>VezSwapchainCreateInfo swapchainCreateInfo = {};
<span class="line-numbers">2</span>swapchainCreateInfo.surface = surface;
<span class="line-numbers">3</span>swapchainCreateInfo.format = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
<span class="line-numbers">4</span>
<span class="line-numbers">5</span>VezSwapchain swapchain = VK_NULL_HANDLE;
<span class="line-numbers">6</span><span class="directive">auto</span> result = vezCreateSwapchain(device, &amp;swapchainCreateInfo, &amp;swapchain);</code></pre>
</div>
</div>
<div class="paragraph">
<p>If the format specified in <code>VezSwapchainCreateInfo</code> was not supported, V-EZ will choose a default one. An application may query the final image format by calling <code>vezGetSwapchainSurfaceFormat</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_putting_it_all_together">2.6. Putting It All Together</h3>
<div class="paragraph">
<p>Below is a coding listing demonstrating each preceeding section.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">  1</span><span class="preprocessor">#include</span> <span class="include">&lt;iostream&gt;</span>
<span class="line-numbers">  2</span><span class="preprocessor">#define</span> GLFW_INCLUDE_NONE
<span class="line-numbers">  3</span><span class="preprocessor">#define</span> GLFW_EXPOSE_NATIVE_WIN32
<span class="line-numbers">  4</span><span class="preprocessor">#include</span> <span class="include">&lt;GLFW/glfw3.h&gt;</span>
<span class="line-numbers">  5</span><span class="preprocessor">#include</span> <span class="include">&lt;GLFW/glfw3native.h&gt;</span>
<span class="line-numbers">  6</span><span class="preprocessor">#include</span> <span class="include">&lt;VEZ.h&gt;</span>
<span class="line-numbers">  7</span>
<span class="line-numbers">  8</span>GLFWwindow* window = <span class="predefined-constant">nullptr</span>;
<span class="line-numbers">  9</span>VkInstance instance = VK_NULL_HANDLE;
<span class="line-numbers"> 10</span>VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
<span class="line-numbers"> 11</span>VkSurfaceKHR surface = VK_NULL_HANDLE;
<span class="line-numbers"> 12</span>VkDevice device = VK_NULL_HANDLE;
<span class="line-numbers"> 13</span>VezSwapchain swapchain = VK_NULL_HANDLE;
<span class="line-numbers"> 14</span>
<span class="line-numbers"> 15</span><span class="predefined-type">bool</span> InitWindow()
<span class="line-numbers"> 16</span>{
<span class="line-numbers"> 17</span>    glfwInit();
<span class="line-numbers"> 18</span>    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
<span class="line-numbers"> 19</span>    window = glfwCreateWindow(<span class="integer">800</span>, <span class="integer">600</span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">MyApplication</span><span class="delimiter">&quot;</span></span>, <span class="predefined-constant">nullptr</span>, <span class="predefined-constant">nullptr</span>);
<span class="line-numbers"> 20</span>    <span class="keyword">if</span> (!window)
<span class="line-numbers"> 21</span>        <span class="keyword">return</span> <span class="predefined-constant">false</span>;
<span class="line-numbers"> 22</span>
<span class="line-numbers"> 23</span>    <span class="keyword">return</span> <span class="predefined-constant">true</span>;
<span class="line-numbers"> 24</span>}
<span class="line-numbers"> 25</span>
<span class="line-numbers"> 26</span><span class="predefined-type">bool</span> InitVulkanEZ()
<span class="line-numbers"> 27</span>{
<span class="line-numbers"> 28</span>    <span class="comment">// Create the V-EZ instance.</span>
<span class="line-numbers"> 29</span>    VezApplicationInfo appInfo = {};
<span class="line-numbers"> 30</span>    appInfo.pApplicationName = <span class="string"><span class="delimiter">&quot;</span><span class="content">MyApplication</span><span class="delimiter">&quot;</span></span>;
<span class="line-numbers"> 31</span>    appInfo.applicationVersion = VK_MAKE_VERSION(<span class="integer">1</span>, <span class="integer">0</span>, <span class="integer">0</span>);
<span class="line-numbers"> 32</span>    appInfo.pEngineName = <span class="string"><span class="delimiter">&quot;</span><span class="content">MyEngine</span><span class="delimiter">&quot;</span></span>;
<span class="line-numbers"> 33</span>    appinfo.engineVersion = VK_MAKE_VERSION(<span class="integer">1</span>, <span class="integer">0</span>, <span class="integer">0</span>);
<span class="line-numbers"> 34</span>
<span class="line-numbers"> 35</span>    VezInstanceCreateInfo instanceCreateInfo = {};
<span class="line-numbers"> 36</span>    instanceCreateInfo.pApplicationInfo = &amp;appInfo;
<span class="line-numbers"> 37</span>
<span class="line-numbers"> 38</span>    VkResult result = vezCreateInstance(&amp;instanceCreateInfo, &amp;instance);
<span class="line-numbers"> 39</span>    <span class="keyword">if</span> (result != VK_SUCCESS)
<span class="line-numbers"> 40</span>        <span class="keyword">return</span> <span class="predefined-constant">false</span>;
<span class="line-numbers"> 41</span>
<span class="line-numbers"> 42</span>    <span class="comment">// Create a surface to render to.</span>
<span class="line-numbers"> 43</span>    result = glfwCreateWindowSurface(instance, window, <span class="predefined-constant">nullptr</span>, &amp;surface);
<span class="line-numbers"> 44</span>    <span class="keyword">if</span> (result != VK_SUCCESS)
<span class="line-numbers"> 45</span>        <span class="keyword">return</span> <span class="predefined-constant">false</span>;
<span class="line-numbers"> 46</span>
<span class="line-numbers"> 47</span>    <span class="comment">// Enumerate and select the first discrete GPU physical device.</span>
<span class="line-numbers"> 48</span>    uint32_t physicalDeviceCount;
<span class="line-numbers"> 49</span>    vezEnumeratePhysicalDevices(instance, &amp;physicalDeviceCount, <span class="predefined-constant">nullptr</span>);
<span class="line-numbers"> 50</span>
<span class="line-numbers"> 51</span>    std::vector&lt;VkPhysicalDevice&gt; physicalDevices(physicalDeviceCount);
<span class="line-numbers"> 52</span>    vezEnumeratePhysicalDevices(instance, &amp;physicalDeviceCount, physicalDevices.data());
<span class="line-numbers"> 53</span>
<span class="line-numbers"> 54</span>    <span class="keyword">for</span> (<span class="directive">auto</span> pd : physicalDevices)
<span class="line-numbers"> 55</span>    {
<span class="line-numbers"> 56</span>        VkPhysicalDeviceProperties properties;
<span class="line-numbers"> 57</span>        vezGetPhysicalDeviceProperties(pd, &amp;properties);
<span class="line-numbers"> 58</span>        <span class="keyword">if</span> (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
<span class="line-numbers"> 59</span>        {
<span class="line-numbers"> 60</span>            physicalDevice = pd;
<span class="line-numbers"> 61</span>            <span class="keyword">break</span>;
<span class="line-numbers"> 62</span>        }
<span class="line-numbers"> 63</span>    }
<span class="line-numbers"> 64</span>
<span class="line-numbers"> 65</span>    <span class="keyword">if</span> (physicalDevice == VK_NULL_HANDLE)
<span class="line-numbers"> 66</span>        <span class="keyword">return</span> <span class="predefined-constant">false</span>;
<span class="line-numbers"> 67</span>
<span class="line-numbers"> 68</span>    <span class="comment">// Create a surface.</span>
<span class="line-numbers"> 69</span>    VezSurfaceCreateInfo createInfo = {};
<span class="line-numbers"> 70</span>    createInfo.hinstance = GetModuleHandle(<span class="predefined-constant">nullptr</span>);
<span class="line-numbers"> 71</span>    createInfo.hwnd = glfwGetWin32Window(window);
<span class="line-numbers"> 72</span>    result = vezCreateSurface(instance, &amp;createInfo, &amp;surface);
<span class="line-numbers"> 73</span>    <span class="keyword">if</span> (result != VK_SUCCESS)
<span class="line-numbers"> 74</span>        <span class="keyword">return</span> <span class="predefined-constant">false</span>;
<span class="line-numbers"> 75</span>
<span class="line-numbers"> 76</span>    <span class="comment">// Create a logical device connection to the physical device.</span>
<span class="line-numbers"> 77</span>    VezDeviceCreateInfo deviceCreateInfo = {};
<span class="line-numbers"> 78</span>    deviceCreateInfo.enabledExtensionCount = <span class="integer">0</span>;
<span class="line-numbers"> 79</span>    deviceCreateInfo.ppEnabledExtensionNames = <span class="predefined-constant">nullptr</span>;
<span class="line-numbers"> 80</span>    result = vezCreateDevice(physicalDevice, &amp;deviceCreateInfo, &amp;device);
<span class="line-numbers"> 81</span>    <span class="keyword">if</span> (result != VK_SUCCESS)
<span class="line-numbers"> 82</span>        <span class="keyword">return</span> <span class="predefined-constant">false</span>;
<span class="line-numbers"> 83</span>
<span class="line-numbers"> 84</span>    <span class="comment">// Create the swapchain.</span>
<span class="line-numbers"> 85</span>    VezSwapchainCreateInfo swapchainCreateInfo = {};
<span class="line-numbers"> 86</span>    swapchainCreateInfo.surface = surface;
<span class="line-numbers"> 87</span>    swapchainCreateInfo.format = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
<span class="line-numbers"> 88</span>    result = vezCreateSwapchain(device, &amp;swapchainCreateInfo, &amp;swapchain);
<span class="line-numbers"> 89</span>    <span class="keyword">if</span> (result != VK_SUCCESS)
<span class="line-numbers"> 90</span>        <span class="keyword">return</span> <span class="predefined-constant">false</span>;
<span class="line-numbers"> 91</span>
<span class="line-numbers"> 92</span>    <span class="keyword">return</span> <span class="predefined-constant">true</span>;
<span class="line-numbers"> 93</span>}
<span class="line-numbers"> 94</span>
<span class="line-numbers"> 95</span><span class="predefined-type">int</span> main(<span class="predefined-type">int</span> argc, <span class="predefined-type">char</span>** argv)
<span class="line-numbers"> 96</span>{
<span class="line-numbers"> 97</span>    <span class="keyword">if</span> (!InitGLFW())
<span class="line-numbers"> 98</span>    {
<span class="line-numbers"> 99</span>        std::cout &lt;&lt; <span class="string"><span class="delimiter">&quot;</span><span class="content">Failed to create GLFW window!</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>;
<span class="line-numbers">100</span>        <span class="keyword">return</span> -<span class="integer">1</span>;
<span class="line-numbers">101</span>    }
<span class="line-numbers">102</span>
<span class="line-numbers">103</span>    <span class="keyword">if</span> (!InitVulkanEZ())
<span class="line-numbers">104</span>    {
<span class="line-numbers">105</span>        std::cout &lt;&lt; <span class="string"><span class="delimiter">&quot;</span><span class="content">Failed to initialize V-EZ!</span><span class="char">\n</span><span class="delimiter">&quot;</span></span>;
<span class="line-numbers">106</span>        <span class="keyword">return</span> -<span class="integer">1</span>;
<span class="line-numbers">107</span>    }
<span class="line-numbers">108</span>
<span class="line-numbers">109</span>    vezDestroyDevice(device);
<span class="line-numbers">110</span>    vezDestroyInstance(instance);
<span class="line-numbers">111</span>    <span class="keyword">return</span> <span class="integer">0</span>;
<span class="line-numbers">112</span>}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_queues">3. Queues</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_queue_families">3.1. Queue Families</h3>
<div class="paragraph">
<p>As discussed in the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#devsandqueues-queues">Vulkan spec</a>, each physical device may have one or more queue families.  A physical device&#8217;s queue families can be queried with <code>vezGetPhysicalDeviceQueueFamilyProperties</code>.  The returned <code>VkQueueFamilyProperties</code> array contains the following fields:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>queueFlags</code> indicating the capabilities of the queues in the queue family</p>
</li>
<li>
<p><code>queueCount</code> a count of queues in this queue family</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>In V-EZ there is no need to explicitly create or request the different queue families.  By default, all queue families and the maximum counts are created and accessible to the application.  An application can obtain <code>VkQueue</code> handles to each queue family by calling <code>vezGetDeviceQueue</code> with the desired <code>queueFamilyIndex</code> and <code>queueIndex</code>, which must be less than <code>queueCount</code> obtained in <code>VkQueueFamilyProperties</code>.  Utility functions are also provided to explicitly request the graphics, compute or transfer queue families.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">1</span><span class="directive">void</span> vezGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);</code></pre>
</div>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">1</span><span class="directive">void</span> vezGetDeviceGraphicsQueue(VkDevice device, uint32_t queueIndex, VkQueue* pQueue);
<span class="line-numbers">2</span><span class="directive">void</span> vezGetDeviceComputeQueue(VkDevice device, uint32_t queueIndex, VkQueue* pQueue);
<span class="line-numbers">3</span><span class="directive">void</span> vezGetDeviceTransferQueue(VkDevice device, uint32_t queueIndex, VkQueue* pQueue);</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>VkQueue</code> handles do not need to be explicitly destroyed by the application.</p>
</div>
</div>
<div class="sect2">
<h3 id="_queue_submission">3.2. Queue Submission</h3>
<div class="paragraph">
<p>Queue submission behavior and syntax in V-EZ is nearly identical to Vulkan.  An application fills in a <code>VezSubmitInfo</code> structure as described in the Vulkan spec.  Please see  <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#devsandqueues-queues">4.3.5 Queue Submission</a> for detailed information on this topic.</p>
</div>
<div class="paragraph">
<p>The primary differences are with respect to semaphores and fences.  In V-EZ, semaphores and fences are never explicitly created by an application.  Instead an application requests them to be created when calling <code>VezQueueSubmit</code> by passing valid, uninitialized, object handles to <code>VezSubmitInfo::pSignalSemaphores</code> and the final <code>pFence</code> parameter of <code>VezQueueSubmit</code>. V-EZ will allocate the objects and store them in these handles. An application is responsible for calling <code>vezDestroyFence</code> for any <code>VkFence</code> object handle returned by V-EZ. As in Vulkan, an application must ensure any queue submission has completed and the <code>VkFence</code> object has been signaled before deletion.</p>
</div>
<div class="paragraph">
<p>For semaphores returned by V-EZ, an application may only pass them to proceeding calls to <code>VezQueueSubmit</code> as wait semaphores. V-EZ will ensure the object handles are properly destroyed after the queue submission completes. External semaphores created by native Vulkan may be passed to V-EZ via <code>VezSubmitInfo::pWaitSemaphores</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span>VkSemaphore semaphore = VK_NULL_HANDLE;
<span class="line-numbers"> 2</span>VkFence fence = VK_NULL_HANDLE;
<span class="line-numbers"> 3</span>
<span class="line-numbers"> 4</span>VezSubmitInfo submitInfo = {};
<span class="line-numbers"> 5</span>submitInfo.commandBufferCount = <span class="integer">1</span>;
<span class="line-numbers"> 6</span>submitInfo.pCommandBuffers = &amp;commandBuffer;
<span class="line-numbers"> 7</span>submitInfo.signalSemaphoreCount = <span class="integer">1</span>;
<span class="line-numbers"> 8</span>submitInfo.pSignalSemaphores = &amp;semaphore;
<span class="line-numbers"> 9</span>VkResult result = vezQueueSubmit(queue, <span class="integer">1</span>, &amp;submitInfo, &amp;fence);
<span class="line-numbers">10</span>
<span class="line-numbers">11</span><span class="comment">// Pass semaphore to another vkQueueSubmit call as a wait semaphore.</span>
<span class="line-numbers">12</span>
<span class="line-numbers">13</span><span class="comment">// Wait on fence to complete.</span>
<span class="line-numbers">14</span>vezWaitForFences(device, <span class="integer">1</span>, &amp;fence, VK_TRUE, ~<span class="integer">0</span>ULL);
<span class="line-numbers">15</span>vezDestroyFence(device, fence);</code></pre>
</div>
</div>
<div class="paragraph">
<p>More on semaphores and fences will be discussed in <a href="#_synchronization">Synchronization</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_queue_presentation">3.3. Queue Presentation</h3>
<div class="paragraph">
<p>V-EZ alleviates most of the responsibility for managing the Vulkan swapchain from the application.  The only operation an application must perform to display a rendered image to a window is call <code>vezQueuePresent</code> with the <code>VezPresentInfo</code> parameter correctly set.  The semantics of <code>VezPresentInfo</code> differ quite a bit from Vulkan&#8217;s <code>VkPresentInfoKHR</code>.  Namely, in V-EZ an application presents a <code>VkImage</code> object handle rather than specifying the image index of the Vulkan swapchain.  Furthermore, V-EZ allows an application to specify signal semaphores in <code>VezPresentInfo</code> which can be used to determine when the <code>VkImage</code> object handle is no longer in use.</p>
</div>
<div class="paragraph">
<p>More than one swapchain may be presented in a single call.  The <code>pImages</code> array must contains the same number of entries as <code>pSwapchains</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span><span class="keyword">typedef</span> <span class="keyword">struct</span> VezPresentInfo {
<span class="line-numbers"> 2</span>    <span class="directive">const</span> <span class="directive">void</span>* pNext;
<span class="line-numbers"> 3</span>    uint32_t waitSemaphoreCount;
<span class="line-numbers"> 4</span>    <span class="directive">const</span> VkSemaphore* pWaitSemaphores;
<span class="line-numbers"> 5</span>    uint32_t swapchainCount;
<span class="line-numbers"> 6</span>    <span class="directive">const</span> VezSwapchain* pSwapchains;
<span class="line-numbers"> 7</span>    <span class="directive">const</span> VkImage* pImages;
<span class="line-numbers"> 8</span>    uint32_t signalSemaphoreCount;
<span class="line-numbers"> 9</span>    VkSemaphore* pSignalSemaphores;
<span class="line-numbers">10</span>    VkResult* pResults;
<span class="line-numbers">11</span>} VkPresentInfo;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The code listing below demonstrates presenting an image the application has rendered into, specifying a single wait semaphore from a previous queue submission and retrieving a signal semaphore.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span>VkSemaphore signalSemaphore = VK_NULL_HANDLE;
<span class="line-numbers"> 2</span>
<span class="line-numbers"> 3</span>VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
<span class="line-numbers"> 4</span>VezPresentInfo presentInfo = {};
<span class="line-numbers"> 5</span>presentInfo.waitSemaphoreCount = <span class="integer">1</span>;
<span class="line-numbers"> 6</span>presentInfo.pWaitSemaphores = &amp;semaphore;
<span class="line-numbers"> 7</span>presentInfo.pWaitDstStageMask = &amp;waitDstStageMask;
<span class="line-numbers"> 8</span>presentInfo.swapchainCount = <span class="integer">1</span>;
<span class="line-numbers"> 9</span>presentInfo.pSwapchains = &amp;swapchain;
<span class="line-numbers">10</span>presentInfo.pImages = &amp;srcImage;
<span class="line-numbers">11</span>presentInfo.signalSemaphoreCount = <span class="integer">1</span>;
<span class="line-numbers">12</span>presentInfo.pSignalSemaphores = &amp;signalSemaphore;
<span class="line-numbers">13</span>VkResult result = vezQueuePresent(graphicsQueue, &amp;presentInfo);
<span class="line-numbers">14</span>
<span class="line-numbers">15</span><span class="comment">// Wait on the signal semaphore before using renderedImage again.</span>
<span class="line-numbers">16</span><span class="comment">// Ex: pass the semaphore to VezSubmitInfo::pWaitSemaphores.</span></code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
Any images passed to <code>VezPresentInfo::pImages</code> must be created with the VK_IMAGE_USAGE_TRANSFER_SRC_BIT usage flag bit. See <a href="#_resource_creation">Resource Creation</a> for details on image creation and usage flags.
</td>
</tr>
</table>
</div>
<div class="sect3">
<h4 id="_multisampled_images">3.3.1. Multisampled Images</h4>
<div class="paragraph">
<p>If any entry in <code>VezPresentInfo::pImages</code> is multisampled, no additional steps need to be taken before calling vezQueuePresent.  V-EZ will automatically resolve the image as its presented to the target window.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_synchronization">4. Synchronization</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In contrast to Vulkan, the application&#8217;s responsibilities for resource access synchronization is partially alleviated by V-EZ.  Namely, <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#synchronization-pipeline-barriers">Pipeline Barriers</a> and <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#synchronization-memory-barriers">Memory Barriers</a> are no longer explicitly required by the application, but handled by V-EZ.  Additionally, fences and semaphores are not explicitly created by the application but requested when calling <code>VkQueueSubmit</code> or <code>vkQueuePresent</code> as previously described in <a href="#_queue_submission">Queue Submission</a>.</p>
</div>
<div class="sect2">
<h3 id="_fences">4.1. Fences</h3>
<div class="paragraph">
<p>As described in the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#synchronization-fences">Vulkan spec</a>, fences are a synchronization primitive that can be used between a queue and the host. In Vulkan, a fence is either signaled, after the execution of a queue submission, or unsignaled after being reset. In V-EZ, fences are never reset.  Once a fence is requested, its status may be queried via <code>vezGetFenceStatus</code> or waited on with <code>vezWaitForFences</code>. An application must call <code>vezDestroyFence</code> when the object is no longer used.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span><span class="comment">// Submit a command buffer to a queue and request a fence object for the submission.</span>
<span class="line-numbers"> 2</span>VkFence fence = VK_NULL_HANDLE;
<span class="line-numbers"> 3</span>
<span class="line-numbers"> 4</span>VezSubmitInfo submitInfo = {};
<span class="line-numbers"> 5</span>submitInfo.commandBufferCount = <span class="integer">1</span>;
<span class="line-numbers"> 6</span>submitInfo.pCommandBuffers = &amp;commandBuffer;
<span class="line-numbers"> 7</span>vezQueueSubmit(queue, <span class="integer">1</span>, &amp;submitInfo, &amp;fence);
<span class="line-numbers"> 8</span>
<span class="line-numbers"> 9</span><span class="comment">// Wait until the queue submission has finished executing.</span>
<span class="line-numbers">10</span>vezWaitForFences(device, <span class="integer">1</span>, &amp;fence, VK_TRUE, ~<span class="integer">0</span>);
<span class="line-numbers">11</span>
<span class="line-numbers">12</span><span class="comment">// Destroy the fence.</span>
<span class="line-numbers">13</span>vezDestroyFence(device, fence);</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_semaphores">4.2. Semaphores</h3>
<div class="paragraph">
<p>Semaphores are a synchronization primitive used to insert dependencies between queue submissions within the same queue or between different queues.  Like fences, semaphores can be signaled or unsignaled.  For a more detailed explanation of semaphores, see the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#synchronization-semaphores">Vulkan spec</a>.</p>
</div>
<div class="paragraph">
<p>An application may obtain semaphore objects when calling <code>vkQueueSubmit</code> or <code>vkQueuePresent</code>.  In both cases, the semaphores are set to be signaled when either operation completes and may be passed as wait semaphores to a proceeding queue submission or present operation.  In V-EZ, semaphores are never explicitly destroyed by the application, rather once they are passed as wait semaphores to a proceeding queue operation, the application no longer maintains ownership. See the previous code listing in <a href="#_queue_presentation">Queue Presentation</a>.</p>
</div>
<div class="paragraph">
<p>The only exception to this behavior is if a semaphore created by VEZ is then passed as a wait semaphore to a native Vulkan queue submission.  In this case, the application must call vezDestroySemaphore once the native Vulkan queue submission completes and the semaphore has been waited on.</p>
</div>
</div>
<div class="sect2">
<h3 id="_events">4.3. Events</h3>
<div class="paragraph">
<p>Events in V-EZ have identical behavior and operation as in Vulkan.  See the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#synchronization-events">Vulkan spec</a> for more information.</p>
</div>
</div>
<div class="sect2">
<h3 id="_wait_idle_operations">4.4. Wait Idle Operations</h3>
<div class="paragraph">
<p>Wait idle operations in V-EZ have identical behavior and operation as in Vulkan.  See the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#synchronization-wait-idle">Vulkan spec</a> for more information.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_pipelines">5. Pipelines</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Pipeline creation and management in V-EZ has been significantly simplified compared to Vulkan. When creating a pipeline in Vulkan, the following graphics state and object handles must be passed to <code>vkCreateGraphicsPipeline</code>.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Vertex input state</p>
</li>
<li>
<p>Input assembly state</p>
</li>
<li>
<p>Viewport state</p>
</li>
<li>
<p>Rasterization state</p>
</li>
<li>
<p>Multisample state</p>
</li>
<li>
<p>Depth stencil state</p>
</li>
<li>
<p>Color blend state</p>
</li>
<li>
<p>Pipeline layout</p>
</li>
<li>
<p>Render passed</p>
</li>
<li>
<p>Subpass index</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>V-EZ alleviates the need to specify any of this information at creation time, thus allowing an application the flexibility to use the same <code>VezPipeline</code> object with different graphics state permutations, vertex attribute bindings and render passes.</p>
</div>
<div class="sect2">
<h3 id="_shader_modules">5.1. Shader Modules</h3>
<div class="paragraph">
<p>Shader modules represent the different shader stages of a pipeline. In Vulkan shader modules can only be created from SPIR-V binaries. However V-EZ allows shader module creation from both SPIR-V and GLSL source. To create a shader module, <code>vezCreateShaderModule</code> is called with <code>VezShaderModuleCreateInfo</code> specifying the stage and GLSL source or SPIR_V binary. The behavior and syntax remain largely the same as Vulkan, with the exception of added GLSL support. The code listing below shows a shader module being created from GLSL source.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span>std::<span class="predefined-type">string</span> glslSource = ReadFile(<span class="string"><span class="delimiter">&quot;</span><span class="content">shader.vert</span><span class="delimiter">&quot;</span></span>);
<span class="line-numbers"> 2</span>
<span class="line-numbers"> 3</span>VezShaderModuleCreateInfo createInfo = {};
<span class="line-numbers"> 4</span>createInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
<span class="line-numbers"> 5</span>createInfo.codeSize = <span class="keyword">static_cast</span>&lt;uint32_t&gt;(glslSource.size());
<span class="line-numbers"> 6</span>createInfo.pGLSLSource = glslSource.c_str();
<span class="line-numbers"> 7</span>createInfo.pEntryPoint = <span class="string"><span class="delimiter">&quot;</span><span class="content">main</span><span class="delimiter">&quot;</span></span>;
<span class="line-numbers"> 8</span>
<span class="line-numbers"> 9</span>VkShaderModule shaderModule = VK_NULL_HANDLE;
<span class="line-numbers">10</span>VkResult result = vezCreateShaderModule(device, &amp;createInfo, &amp;shaderModule);</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>VezShaderModuleCreateInfo::pEntryPoint</code> field is only required when creating a shader module from GLSL source. For more information on shader modules, please see the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#shader-modules">Vulkan spec</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_graphics_pipelines">5.2. Graphics Pipelines</h3>
<div class="paragraph">
<p>To create a graphics pipeline, call <code>vezCreateGraphicsPipeline</code> with an array of <code>VezPipelineShaderStageCreateInfo</code> entries, one for each shader stage the pipeline will use. The code listing below assumes vertex and fragment shader modules have already been created.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span>std::array&lt;VezPipelineShaderStageCreateInfo, <span class="integer">2</span>&gt; stages = { { {}, {} } };
<span class="line-numbers"> 2</span>stages[<span class="integer">0</span>] = {};
<span class="line-numbers"> 3</span>stages[<span class="integer">0</span>].module = vertexStageShaderModule;
<span class="line-numbers"> 4</span>stages[<span class="integer">0</span>].pEntryPoint = <span class="predefined-constant">nullptr</span>;
<span class="line-numbers"> 5</span>stages[<span class="integer">1</span>] = {};
<span class="line-numbers"> 6</span>stages[<span class="integer">1</span>].module = fragmentStageShaderModule;
<span class="line-numbers"> 7</span>stages[<span class="integer">1</span>].pEntryPoint = <span class="predefined-constant">nullptr</span>;
<span class="line-numbers"> 8</span>
<span class="line-numbers"> 9</span>VezGraphicsPipelineCreateInfo createInfo = {};
<span class="line-numbers">10</span>createInfo.stageCount = <span class="keyword">static_cast</span>&lt;uint32_t&gt;(stages.size());
<span class="line-numbers">11</span>createInfo.pStages = stages.data();
<span class="line-numbers">12</span>
<span class="line-numbers">13</span>VezPipeline pipeline = VK_NULL_HANDLE;
<span class="line-numbers">14</span>VkResult result = vezCreateGraphicsPipeline(device, &amp;createInfo, &amp;pipeline);</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>VezPipelineShaderStageCreateInfo::pEntryPoint</code> allows an application to re-specify alternate entry points for a shader module. This is useful in the case where a single shader module contains multiple entry points for a given shader stage and used between more than one pipeline.</p>
</div>
</div>
<div class="sect2">
<h3 id="_compute_pipelines">5.3. Compute Pipelines</h3>
<div class="paragraph">
<p>Compute pipelines are created with a single <code>VezPipelineShaderStageCreateInfo</code> object and a call to <code>vezCreateComputePipeline</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_specialization_constants">5.4. Specialization Constants</h3>
<div class="paragraph">
<p>Specialization constants in V-EZ work the same as they do in Vulkan. An application sets <code>VezPipelineShaderStageCreateInfo::pSpecializationInfo</code> accordingly. For more information on specialization constants, please see the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#pipelines-specialization-constants">Vulkan spec</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_push_constants">5.5. Push Constants</h3>
<div class="paragraph">
<p>Push constants are a "<em>high speed path to modify constant data in pipelines that is expected to out perform memory-backed resource updates</em>". For more information on push constants, please see the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#descriptorsets-pipelinelayout">Vulkan spec</a>.</p>
</div>
<div class="paragraph">
<p>V-EZ simplifies the use of push constants by only requiring an application call <code>vezCmdPushConstants</code> to update the memory, requiring only an offset, size and pointer to host data to update the push constants memory with. A valid pipeline must be bound before calling <code>vezCmdPushConstants</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">1</span><span class="directive">void</span> vezCmdPushConstants(VezCommandBuffer commandBuffer, uint32_t offset, uint32_t size, <span class="directive">const</span> <span class="directive">void</span>* pValues);</code></pre>
</div>
</div>
<div class="paragraph">
<p>In the case where multiple shader stages within a pipeline define push constants at different byte offsets, an application may query these offsets and sizes with V-EZ&#8217;s pipeline reflection described in the next section.</p>
</div>
</div>
<div class="sect2">
<h3 id="_pipeline_reflection">5.6. Pipeline Reflection</h3>
<div class="paragraph">
<p>Unlike Vulkan, V-EZ allows full pipeline shader stage reflection if the shader stages were created from GLSL source, or the SPIR-V binary source contains the relevant meta-data. To enumerate all pipeline resources call <code>vezEnumeratePipelineResources</code>, which returns an array of <code>VkPipelineResource</code> entries.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span><span class="keyword">typedef</span> <span class="keyword">struct</span> VezMemberInfo
<span class="line-numbers"> 2</span>{
<span class="line-numbers"> 3</span>    VezBaseType baseType;
<span class="line-numbers"> 4</span>    uint32_t offset;
<span class="line-numbers"> 5</span>    uint32_t size;
<span class="line-numbers"> 6</span>    uint32_t vecSize;
<span class="line-numbers"> 7</span>    uint32_t arraySize;
<span class="line-numbers"> 8</span>    <span class="predefined-type">char</span> name[VK_MAX_DESCRIPTION_SIZE];
<span class="line-numbers"> 9</span>    <span class="directive">const</span> VezMemberInfo* pNext;
<span class="line-numbers">10</span>    <span class="directive">const</span> VezMemberInfo* pMembers;
<span class="line-numbers">11</span>} VezMemberInfo;
<span class="line-numbers">12</span>
<span class="line-numbers">13</span><span class="keyword">typedef</span> <span class="keyword">struct</span> VezPipelineResource {
<span class="line-numbers">14</span>    VkShaderStageFlags stages;
<span class="line-numbers">15</span>    VezPipelineResourceType resourceType;
<span class="line-numbers">16</span>    VezBaseType baseType;
<span class="line-numbers">17</span>    VkAccessFlags access;
<span class="line-numbers">18</span>    uint32_t set;
<span class="line-numbers">19</span>    uint32_t binding;
<span class="line-numbers">20</span>    uint32_t location;
<span class="line-numbers">21</span>    uint32_t inputAttachmentIndex;
<span class="line-numbers">22</span>    uint32_t vecSize;
<span class="line-numbers">23</span>    uint32_t arraySize;
<span class="line-numbers">24</span>    uint32_t offset;
<span class="line-numbers">25</span>    uint32_t size;
<span class="line-numbers">26</span>    <span class="predefined-type">char</span> name[VK_MAX_DESCRIPTION_SIZE];
<span class="line-numbers">27</span>    <span class="directive">const</span> VezMemberInfo* pMembers;
<span class="line-numbers">28</span>} VezPipelineResource;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <strong>stages</strong> field is a bitmask of all shader stages the resource is used in. For example, a the same uniform buffer binding might be bound and accessed in both the vertex and fragment shader stages.</p>
</div>
<div class="paragraph">
<p>The <strong>resourceType</strong> field specifies one of the following values:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span><span class="keyword">typedef</span> <span class="keyword">enum</span> VezPipelineResourceType {
<span class="line-numbers"> 2</span>    VEZ_PIPELINE_RESOURCE_TYPE_INPUT = <span class="integer">0</span>,
<span class="line-numbers"> 3</span>    VEZ_PIPELINE_RESOURCE_TYPE_OUTPUT = <span class="integer">1</span>,
<span class="line-numbers"> 4</span>    VEZ_PIPELINE_RESOURCE_TYPE_SAMPLER = <span class="integer">2</span>,
<span class="line-numbers"> 5</span>    VEZ_PIPELINE_RESOURCE_TYPE_COMBINED_IMAGE_SAMPLER = <span class="integer">3</span>,
<span class="line-numbers"> 6</span>    VEZ_PIPELINE_RESOURCE_TYPE_SAMPLED_IMAGE = <span class="integer">4</span>,
<span class="line-numbers"> 7</span>    VEZ_PIPELINE_RESOURCE_TYPE_STORAGE_IMAGE = <span class="integer">5</span>,
<span class="line-numbers"> 8</span>    VEZ_PIPELINE_RESOURCE_TYPE_UNIFORM_TEXEL_BUFFER = <span class="integer">6</span>,
<span class="line-numbers"> 9</span>    VEZ_PIPELINE_RESOURCE_TYPE_STORAGE_TEXEL_BUFFER = <span class="integer">7</span>,
<span class="line-numbers">10</span>    VEZ_PIPELINE_RESOURCE_TYPE_UNIFORM_BUFFER = <span class="integer">8</span>,
<span class="line-numbers">11</span>    VEZ_PIPELINE_RESOURCE_TYPE_STORAGE_BUFFER = <span class="integer">9</span>,
<span class="line-numbers">12</span>    VEZ_PIPELINE_RESOURCE_TYPE_ATOMIC_COUNTER = <span class="integer">10</span>,
<span class="line-numbers">13</span>    VEZ_PIPELINE_RESOURCE_TYPE_PUSH_CONSTANT_BUFFER = <span class="integer">11</span>,
<span class="line-numbers">14</span>} VezPipelineResourceType;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <strong>baseType</strong> field specifies the data type. For GLSL vec4, baseType would be VEZ_PIPELINE_RESOURCE_BASE_TYPE_FLOAT for example.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span><span class="keyword">typedef</span> <span class="keyword">enum</span> VezBaseType {
<span class="line-numbers"> 2</span>    VEZ_BASE_TYPE_BOOL = <span class="integer">0</span>,
<span class="line-numbers"> 3</span>    VEZ_BASE_TYPE_CHAR = <span class="integer">1</span>,
<span class="line-numbers"> 4</span>    VEZ_BASE_TYPE_INT = <span class="integer">2</span>,
<span class="line-numbers"> 5</span>    VEZ_BASE_TYPE_UINT = <span class="integer">3</span>,
<span class="line-numbers"> 6</span>    VEZ_BASE_TYPE_UINT64 = <span class="integer">4</span>,
<span class="line-numbers"> 7</span>    VEZ_BASE_TYPE_HALF = <span class="integer">5</span>,
<span class="line-numbers"> 8</span>    VEZ_BASE_TYPE_FLOAT = <span class="integer">6</span>,
<span class="line-numbers"> 9</span>    VEZ_BASE_TYPE_DOUBLE = <span class="integer">7</span>,
<span class="line-numbers">10</span>    VEZ_BASE_TYPE_STRUCT = <span class="integer">8</span>,
<span class="line-numbers">11</span>} VezBaseType;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <strong>access</strong> field specifies whether the resource has read and/or write access.</p>
</div>
<div class="paragraph">
<p>The <strong>set</strong> and <strong>binding</strong> fields specify the set number and binding point in the shader as declared in the GLSL source or SPIR-V binary. For additional information on this, please see the <a href="#_glsl_guide">GLSL Guide</a> at the end of this document.</p>
</div>
<div class="paragraph">
<p>For shader stage inputs and outputs, the <strong>location</strong> field specifies the location binding. Examples include fragment stage output, inputs and outputs between shader stages, etc.</p>
</div>
<div class="paragraph">
<p>For renderpass subpasses, the <strong>inputAttachmentIndex</strong> specifies the index the attachment is bound to.</p>
</div>
<div class="paragraph">
<p>The <strong>vecSize</strong> field specifies the number of components. If the shader resource is vec3, vecSize will equal 3. For scalar pipeline resources, vecSize will be 1.</p>
</div>
<div class="paragraph">
<p>The 'arraySize' field specifies the number of elements in the pipeline resource&#8217;s array declaration. For example, in the code listing below, the arraySize would be 10.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">1</span>layout (set=<span class="integer">0</span>, binding=<span class="integer">0</span>) uniform sampler2D textures[<span class="integer">10</span>];</code></pre>
</div>
</div>
<div class="paragraph">
<p>The 'offset' and 'size' specify the byte offset and byte size of a resource when declared inside of a struct.</p>
</div>
<div class="paragraph">
<p>If an application knows the name of the pipeline resource to query, <code>vkGetPipelineResource</code> may be used.</p>
</div>
<div class="paragraph">
<p>For uniform and shader storage buffer objects, the <strong>pMembers</strong> field forms a multi-level linked list of members of these structured bindings. See the <strong>PipelineReflection</strong> sample for how to iterate over these.</p>
</div>
</div>
<div class="sect2">
<h3 id="_pipeline_binding">5.7. Pipeline Binding</h3>
<div class="paragraph">
<p>Graphics pipelines must be bound between <code>vezCmdBeginRenderPass</code> and <code>vezCmdEndRenderPass</code> calls. Compute pipelines must be bound outside of a render pass.  To bind a pipeline, call <code>vezCmdBindPipeline</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_vertex_input_formats">6. Vertex Input Formats</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In Vulkan the expected vertex input state must be specified at graphics pipeline creation time. The downside to this is that an application must manage different permutations of the same pipeline if it&#8217;s used with more than one vertex input format.  The vertex input format consists of an array of vertex binding descriptions, via <code>VkVertexInputBindingDescription</code>, and vertex attribute descriptions, via <code>VkVertexInputAttributeDescription</code>.</p>
</div>
<div class="paragraph">
<p>V-EZ alleviates this requirement, as graphics pipeline creation only requires an array of shader modules (<a href="#_graphics_pipelines">Graphics Pipelines</a>).  Instead, the desired vertex input format is set during command buffer recording by calling <code>vezCmdSetVertexInputFormat</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">1</span><span class="directive">void</span> vezCmdSetVertexInputFormat(VkCommandBuffer commandBuffer, VezVertexInputFormat format);</code></pre>
</div>
</div>
<div class="sect2">
<h3 id="_creation">6.1. Creation</h3>
<div class="paragraph">
<p>An application now only needs to manage vertex input formats at the mesh or object level.  V-EZ moves the specification of the <code>VkVertexInputBindingDescription</code> and <code>VkVertexInputAttributeDescription</code> arrays to the <code>VkVertexInputFormat</code> object creation.  In the code listing below, a vertex input format is created specifying a single binding point and two vertex attributes.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span><span class="comment">// All vertex attributes bound using a single buffer binding point.</span>
<span class="line-numbers"> 2</span>VkVertexInputBindingDescription bindingDescription = {};
<span class="line-numbers"> 3</span>bindingDescription.binding = <span class="integer">0</span>;
<span class="line-numbers"> 4</span>bindingDescription.stride = <span class="keyword">sizeof</span>(<span class="predefined-type">float</span>) * <span class="integer">5</span>;
<span class="line-numbers"> 5</span>bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
<span class="line-numbers"> 6</span>
<span class="line-numbers"> 7</span><span class="comment">// XYZ position and XY texture coordinate attributes declared.</span>
<span class="line-numbers"> 8</span>std::array&lt;VkVertexInputAttributeDescription, <span class="integer">2</span>&gt; attributeDescriptions;
<span class="line-numbers"> 9</span>attributeDescriptions[<span class="integer">0</span>].location = <span class="integer">0</span>;
<span class="line-numbers">10</span>attributeDescriptions[<span class="integer">0</span>].binding = <span class="integer">0</span>;
<span class="line-numbers">11</span>attributeDescriptions[<span class="integer">0</span>].offset = <span class="integer">0</span>;
<span class="line-numbers">12</span>attributeDescriptions[<span class="integer">0</span>].format = VK_FORMAT_R32G32B32_SFLOAT;
<span class="line-numbers">13</span>attributeDescriptions[<span class="integer">1</span>].location = <span class="integer">1</span>;
<span class="line-numbers">14</span>attributeDescriptions[<span class="integer">1</span>].binding = <span class="integer">0</span>;
<span class="line-numbers">15</span>attributeDescriptions[<span class="integer">1</span>].offset = <span class="keyword">sizeof</span>(<span class="predefined-type">float</span>) * <span class="integer">3</span>;
<span class="line-numbers">16</span>attributeDescriptions[<span class="integer">1</span>].format = VK_FORMAT_R32G32_SFLOAT;
<span class="line-numbers">17</span>
<span class="line-numbers">18</span>VezVertexInputFormatCreateInfo createInfo = {};
<span class="line-numbers">19</span>createInfo.vertexBindingDescriptionCount = <span class="integer">1</span>;
<span class="line-numbers">20</span>createInfo.pVertexBindingDescriptions = &amp;bindingDescription;
<span class="line-numbers">21</span>createInfo.vertexAttributeDescriptionCount = <span class="keyword">static_cast</span>&lt;uin32_t&gt;(attributeDescriptions.size());
<span class="line-numbers">22</span>createInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
<span class="line-numbers">23</span>
<span class="line-numbers">24</span>VezVertexInputFormat vertexInputFormat = VK_NULL_HANDLE;
<span class="line-numbers">25</span>VkResult result = vezCreateVertexInputFormat(device, &amp;createInfo, &amp;vertexInputFormat);</code></pre>
</div>
</div>
<div class="paragraph">
<p>The rules and semantics of specifying <code>VkVertexInputBindingDescription</code> and <code>VkVertexInputAttributeDescription</code> follow the same rules as specified in the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkPipelineVertexInputStateCreateInfo.html">Vulkan spec</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_destruction">6.2. Destruction</h3>
<div class="paragraph">
<p>When an application no longer requires a <code>VezVertexInputFormat</code> it should be destroyed by calling <code>vezDestroyVertexInputFormat</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_resource_creation">7. Resource Creation</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Like Vulkan, V-EZ supports two low-level resource types: <em>buffers</em> and <em>images</em>. However V-EZ does not require an application to manage the underlying memory, which is completely abstracted away. All the application sees are <code>VkBuffer</code> and <code>VkImage</code> objects. For more information on resource creation and memory, see the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#resources">Vulkan spec</a>.</p>
</div>
<div class="paragraph">
<p>Since memory management is hidden from the application, V-EZ exposes <code>VezMemoryFlags</code> when creating buffers and images. These flags allow an application to specify how the memory will be used and where the it should reside.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">1</span><span class="keyword">typedef</span> <span class="keyword">enum</span> VezMemoryFlagsBits {
<span class="line-numbers">2</span>    VEZ_MEMORY_GPU_ONLY = <span class="hex">0x00000000</span>,
<span class="line-numbers">3</span>    VEZ_MEMORY_CPU_ONLY = <span class="hex">0x00000001</span>,
<span class="line-numbers">4</span>    VEZ_MEMORY_CPU_TO_GPU = <span class="hex">0x00000002</span>,
<span class="line-numbers">5</span>    VEZ_MEMORY_GPU_TO_CPU = <span class="hex">0x00000004</span>,
<span class="line-numbers">6</span>    VEZ_MEMORY_DEDICATED_ALLOCATION = <span class="hex">0x00000008</span>,
<span class="line-numbers">7</span>} VezMemoryFlagsBits;</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>VEZ_MEMORY_GPU_ONLY</strong> specifies a buffer or image memory backing should reside in a device&#8217;s local memory only.</p>
</div>
<div class="paragraph">
<p><strong>VEZ_MEMORY_CPU_ONLY</strong> specifies a buffer or image memory backing should reside in host memory.</p>
</div>
<div class="paragraph">
<p><strong>VEZ_MEMORY_CPU_TO_GPU</strong> specifies a buffer or image memory backing should be optimized for data transfers from the host to the device.</p>
</div>
<div class="paragraph">
<p><strong>VEZ_MEMORY_GPU_TO_CPU</strong> specifies a buffer or image memory backing should be optimized for data transfers from the device to the host.</p>
</div>
<div class="paragraph">
<p><strong>VEZ_MEMORY_DEDICATED_ALLOCATION</strong> specifies that the buffer or image should use a unique memory block.</p>
</div>
<div class="paragraph">
<p>V-EZ&#8217;s internal memory management sub-allocates memory blocks by default.  If an application prefers that a particular buffer or image have its own dedicated memory block, <strong>VEZ_MEMORY_DEDICATED_ALLOCATION</strong> can be used.</p>
</div>
<div class="sect2">
<h3 id="_buffers">7.1. Buffers</h3>
<div class="paragraph">
<p>Buffers are represented by <code>VkBuffer</code> handles and created by calling <code>vkCreateBuffer</code>. The code listing below demonstrates creating a buffer to be used for <em>staging</em>, or data transfers optimized for host to device.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">1</span>VezBufferCreateInfo createInfo = {};
<span class="line-numbers">2</span>createInfo.size = (<span class="integer">32</span> &lt;&lt; <span class="integer">20</span>ULL) <span class="comment">// 32 megabytes</span>
<span class="line-numbers">3</span>createInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
<span class="line-numbers">4</span>
<span class="line-numbers">5</span>VkBuffer buffer = VK_NULL_HANDLE;
<span class="line-numbers">6</span>VkResult result = vezCreateBuffer(device, VEZMEMORY_CPU_TO_GPU, &amp;createInfo, &amp;buffer);</code></pre>
</div>
</div>
<div class="paragraph">
<p>The application must always specify the intended usage for a buffer using the <code>VezBufferUsageFlagBits</code> enumeration values. In the code listing above, the buffer is only used as a <em>source</em> for data transfers.</p>
</div>
<div class="paragraph">
<p>Like Vulkan, V-EZ allows an application to specify an array of queue family indices the buffer will be used with. If an application sets <code>queueFamilyIndexCount</code> to 0, V-EZ defaults the buffer to being accessible to all queue families.</p>
</div>
<div class="paragraph">
<p>When a <code>VkBuffer</code> handle is no longer used by an application, it should be destroyed with <code>vezDestroyBuffer</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_buffer_views">7.2. Buffer Views</h3>
<div class="paragraph">
<p>Creating buffer views from buffers has nearly identical syntax to Vulkan. An application calls <code>vezCreateBufferView</code> with appropriate values for fields in <code>VezBufferViewCreateInfo</code>. Buffer views are destroyed by calling <code>vezDestroyBufferView</code>.  For more information on buffer views, see the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#resources-buffer-views">Vulkan spec</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_images">7.3. Images</h3>
<div class="paragraph">
<p>Images are represented by <code>VkImage</code> handles and created by calling <code>vezCreateImage</code>.  Like buffers, <code>VezMemoryFlags</code> is passed to <code>vezCreateImage</code> allowing an application to specify how the memory will be used and where the it should reside.  The syntax and behavior of <code>vezCreateImage</code> and <code>VezImageCreateInfo</code> in V-EZ are nearly identical to Vulkan, see the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#resources-images">Vulkan spec</a> for more information.</p>
</div>
<div class="paragraph">
<p>As with buffers, if the <strong>queueFamilyIndexCount</strong> in <code>VezImageCreateInfo</code> is set to 0, then V-EZ assumes the image will be used with all available queue families.</p>
</div>
</div>
<div class="sect2">
<h3 id="_image_views">7.4. Image Views</h3>
<div class="paragraph">
<p>See the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#resources-image-views">Vulkan spec</a> for more information on image views.  The behavior and syntax in V-EZ is nearly identical to Vulkan.</p>
</div>
</div>
<div class="sect2">
<h3 id="_framebuffers">7.5. Framebuffers</h3>
<div class="paragraph">
<p>In Vulkan, an application must specify an array of <code>VkImageView</code> attachments, a <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#renderpass-compatibility">compatible</a> Render Pass, and the dimensions when creating a framebuffer.  V-EZ simplifies this to only requiring the array of attachments and the dimensions.  Render passes are never explicitly created by applications V-EZ (see <a href="#_render_passes">Render Passes</a>), and therefore are not required when creating a framebuffer.</p>
</div>
<div class="paragraph">
<p>The coding listing below demonstrates creating a simple framebuffer from a color and depth image. Note that the usage parameter for the color image has the VK_IMAGE_USAGE_TRANSFER_SRC_BIT set.  This is required for any image presented to a window when calling <code>vezQueuePresent</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span><span class="comment">// Create the color image.</span>
<span class="line-numbers"> 2</span>VezImageCreateInfo imageCreateInfo = {};
<span class="line-numbers"> 3</span>imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
<span class="line-numbers"> 4</span>imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
<span class="line-numbers"> 5</span>imageCreateInfo.extent = { width, height, <span class="integer">1</span> };
<span class="line-numbers"> 6</span>imageCreateInfo.mipLevels = <span class="integer">1</span>;
<span class="line-numbers"> 7</span>imageCreateInfo.arrayLayers = <span class="integer">1</span>;
<span class="line-numbers"> 8</span>imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
<span class="line-numbers"> 9</span>imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
<span class="line-numbers">10</span>imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
<span class="line-numbers">11</span>
<span class="line-numbers">12</span>VkImage colorImage = VK_NULL_HANDLE;
<span class="line-numbers">13</span>vezCreateImage(device, VEZ_MEMORY_GPU_ONLY, &amp;imageCreateInfo, &amp;colorImage);
<span class="line-numbers">14</span>
<span class="line-numbers">15</span><span class="comment">// Create the image view.</span>
<span class="line-numbers">16</span>VezImageViewCreateInfo imageViewCreateInfo = {};
<span class="line-numbers">17</span>imageViewCreateInfo.image = colorImage;
<span class="line-numbers">18</span>imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
<span class="line-numbers">19</span>imageViewCreateInfo.format = imageCreateInfo.format;
<span class="line-numbers">20</span>imageViewCreateInfo.subresourceRange.layerCount = <span class="integer">1</span>;
<span class="line-numbers">21</span>imageViewCreateInfo.subresourceRange.levelCount = <span class="integer">1</span>;
<span class="line-numbers">22</span>
<span class="line-numbers">23</span>VkImageView colorImageView = VK_NULL_HANDLE;
<span class="line-numbers">24</span>vezCreateImageView(device, &amp;imageViewCreateInfo, &amp;colorImageView);
<span class="line-numbers">25</span>
<span class="line-numbers">26</span><span class="comment">// Create the depth image attachment.</span>
<span class="line-numbers">27</span>imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
<span class="line-numbers">28</span>imageCreateInfo.format = VK_FORMAT_D32_SFLOAT;
<span class="line-numbers">29</span>imageCreateInfo.extent = { width, height, <span class="integer">1</span> };
<span class="line-numbers">30</span>imageCreateInfo.mipLevels = <span class="integer">1</span>;
<span class="line-numbers">31</span>imageCreateInfo.arrayLayers = <span class="integer">1</span>;
<span class="line-numbers">32</span>imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
<span class="line-numbers">33</span>imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
<span class="line-numbers">34</span>imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
<span class="line-numbers">35</span>
<span class="line-numbers">36</span>VkImage depthImage = VK_NULL_HANDLE;
<span class="line-numbers">37</span>vezCreateImage(device, VEZ_MEMORY_GPU_ONLY, &amp;imageCreateInfo, &amp;depthImage);
<span class="line-numbers">38</span>
<span class="line-numbers">39</span><span class="comment">// Create the image view.</span>
<span class="line-numbers">40</span>imageViewCreateInfo.image = depthImage;
<span class="line-numbers">41</span>imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
<span class="line-numbers">42</span>imageViewCreateInfo.format = imageCreateInfo.format;
<span class="line-numbers">43</span>imageViewCreateInfo.subresourceRange.layerCount = <span class="integer">1</span>;
<span class="line-numbers">44</span>imageViewCreateInfo.subresourceRange.levelCount = <span class="integer">1</span>;
<span class="line-numbers">45</span>
<span class="line-numbers">46</span>VkImageView depthImageView = VK_NULL_HANDLE;
<span class="line-numbers">47</span>vezCreateImageView(device, &amp;imageViewCreateInfo, &amp;depthImageView);
<span class="line-numbers">48</span>
<span class="line-numbers">49</span><span class="comment">// Create the framebuffer.</span>
<span class="line-numbers">50</span>std::array&lt;VkImageView, <span class="integer">2</span>&gt; attachments = { colorImageView, depthImageView };
<span class="line-numbers">51</span>VezFramebufferCreateInfo framebufferCreateInfo = {};
<span class="line-numbers">52</span>framebufferCreateInfo.attachmentCount = <span class="keyword">static_cast</span>&lt;uint32_t&gt;(attachments.size());
<span class="line-numbers">53</span>framebufferCreateInfo.pAttachments = attachments.data();
<span class="line-numbers">54</span>framebufferCreateInfo.width = width;
<span class="line-numbers">55</span>framebufferCreateInfo.height = height;
<span class="line-numbers">56</span>framebufferCreateInfo.depth = <span class="integer">1</span>;
<span class="line-numbers">57</span>VezFramebuffer framebuffer = VK_NULL_HANDLE;
<span class="line-numbers">58</span>vezCreateFramebuffer(device, &amp;framebufferCreateInfo, &amp;framebuffer);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Framebuffers are destroyed by calling <code>vezDestroyFramebuffer</code>.</p>
</div>
<div class="sect3">
<h4 id="_multisampled_framebuffers">7.5.1. Multisampled Framebuffers</h4>
<div class="paragraph">
<p>An application may create a multisampled framebuffer by setting <code>VezImageCreateInfo::samples</code> to the appropriate value when creating the color and depth stencil attachments.  Then the multisample state block must be set appropriately to enable multisampled rendering (see <a href="#_graphics_state">Graphics State</a>).</p>
</div>
</div>
<div class="sect3">
<h4 id="_framebuffers_with_no_attachments">7.5.2. Framebuffers With No Attachments</h4>
<div class="paragraph">
<p>As described in the Vulkan specification, framebuffers with no attachments but valid dimensions may still be created. To create a framebuffer with no attachments in V-EZ, simply set <code>VezFramebufferCreateInfo::pAttachments</code> to null and <code>VezFramebufferCreateInfo::attachmentCount</code> to 0.  Then set appropriate values for width, height, depth and samples.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_samplers">8. Samplers</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Sampler creation and usage in V-EZ is identical to Vulkan.  For more information, see the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#samplers">Vulkan spec</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_command_buffers">9. Command Buffers</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The primary differences between Vulkan and V-EZ with respect to command buffers are the removal of command pools and secondary command buffers in V-EZ. An application need no longer manage individual command pools across threads. Only <code>VkCommandBuffer</code> handles are created by an applications in V-EZ.</p>
</div>
<div class="paragraph">
<p>A secondary difference is with respect to pipeline barriers. As previously stated in <a href="#_synchronization">Synchronization</a>, V-EZ does not expose pipeline barriers. Within a command buffer, and between command buffer submissions, pipeline barriers are inserted automatically. An application is no longer responsible for managing this level of synchronization.</p>
</div>
<div class="paragraph">
<p>Other aspects of command buffers, such as state persistence within a command buffer, is identical to Vulkan. Existing Vulkan command buffer commands are also present, along with additional ones (see <a href="#_resource_binding">Resource Binding</a>).</p>
</div>
<div class="sect2">
<h3 id="_allocation_and_management">9.1. Allocation and Management</h3>
<div class="paragraph">
<p>To create a command buffer an application calls <code>vezAllocateCommandBuffers</code>. The intended <strong>queue</strong> the command buffer will be used on must be specified.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers">1</span>VkQueue graphicsQueue = VK_NULL_HANDLE;
<span class="line-numbers">2</span>vezGetDeviceGraphicsQueue(device, <span class="integer">0</span>, &amp;graphicsQueue);
<span class="line-numbers">3</span>
<span class="line-numbers">4</span>VezCommandBufferAllocateInfo allocInfo = {};
<span class="line-numbers">5</span>allocInfo.queue = graphicsQueue;
<span class="line-numbers">6</span>allocInfo.commandBufferCount = <span class="integer">1</span>;
<span class="line-numbers">7</span>VezCommandBuffer commandBuffer = VK_NULL_HANDLE;
<span class="line-numbers">8</span>VkResult result = vezAllocateCommandBuffers(device, &amp;allocInfo, &amp;commandBuffer);</code></pre>
</div>
</div>
<div class="paragraph">
<p>A command buffer must be destroyed by calling <code>vezFreeCommandBuffers</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_recording">9.2. Recording</h3>
<div class="paragraph">
<p>An application may begin recording commands to a <code>VkCommandBuffer</code> handle by calling <code>vezBeginCommandBuffer</code>. The only required parameter is <code>VkCommandBufferUsageFlags</code> which gives hints to the driver about how it will be used. See the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkCommandBufferUsageFlagBits.html">Vulkan spec</a> for more details. Unlike native Vulkan, V-EZ&#8217;s equivalent command buffer functions do not require the VkCommandBuffer handle be passed in. Rather, all vezCmd* functions are associated with the VkCommandBuffer passed to vezBeginCommandBuffer within the same application thread. Commands recorded across threads must indepdently call vezBeginCommandBuffer. An application ends recording by calling <code>vezEndCommandBuffer</code>.</p>
</div>
<div class="paragraph">
<p>Like Vulkan, an application must wait for a previously submitted <code>VkCommandBuffer</code> object handle to not be in use before re-recording. Applications should track queue submissions with fences and query the fence status, or wait, before re-recording commands. See fences under <a href="#_synchronization">Synchronization</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_graphics_state">9.3. Graphics State</h3>
<div class="paragraph">
<p>As described in <a href="#_pipelines">Pipelines</a>, V-EZ removes all graphics state specification from pipeline creation. In V-EZ, graphics state is set dynamically while recording a command buffer. Furthermore, all available <a href="https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkDynamicState.html">dynamic states</a> from Vulkan are enabled by default and their corresponding command buffer functions made available in V-EZ. States are not required to be set within a render pass. The following is a list of states available to be set.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span><span class="keyword">typedef</span> <span class="keyword">struct</span> VezInputAssemblyState {
<span class="line-numbers"> 2</span>    VkPrimitiveTopology topology;
<span class="line-numbers"> 3</span>    VkBool32 primitiveRestartEnable;
<span class="line-numbers"> 4</span>} VezInputAssemblyState;
<span class="line-numbers"> 5</span>
<span class="line-numbers"> 6</span><span class="keyword">typedef</span> <span class="keyword">struct</span> VezRasterizationState {
<span class="line-numbers"> 7</span>    VkBool32 depthClampEnable;
<span class="line-numbers"> 8</span>    VkBool32 rasterizerDiscardEnable;
<span class="line-numbers"> 9</span>    VkPolygonMode polygonMode;
<span class="line-numbers">10</span>    VkCullModeFlags cullMode;
<span class="line-numbers">11</span>    VkFrontFace frontFace;
<span class="line-numbers">12</span>    VkBool32 depthBiasEnable;
<span class="line-numbers">13</span>    <span class="predefined-type">float</span> depthBiasConstantFactor;
<span class="line-numbers">14</span>    <span class="predefined-type">float</span> depthBiasClamp;
<span class="line-numbers">15</span>    <span class="predefined-type">float</span> depthBiasSlopeFactor;
<span class="line-numbers">16</span>} VezRasterizationState;
<span class="line-numbers">17</span>
<span class="line-numbers">18</span><span class="keyword">typedef</span> <span class="keyword">struct</span> VezMultisampleState {
<span class="line-numbers">19</span>    VkSampleCountFlagBits rasterizationSamples;
<span class="line-numbers">20</span>    VkBool32 sampleShadingEnable;
<span class="line-numbers">21</span>    <span class="predefined-type">float</span> minSampleShading;
<span class="line-numbers">22</span>    <span class="directive">const</span> VkSampleMask* pSampleMask;
<span class="line-numbers">23</span>    VkBool32 alphaToCoverageEnable;
<span class="line-numbers">24</span>    VkBool32 alphaToOneEnable;
<span class="line-numbers">25</span>} VezMultisampleStateCreateInfo;
<span class="line-numbers">26</span>
<span class="line-numbers">27</span><span class="keyword">typedef</span> <span class="keyword">struct</span> VezStencilOpState {
<span class="line-numbers">28</span>    VkStencilOp failOp;
<span class="line-numbers">29</span>    VkStencilOp passOp;
<span class="line-numbers">30</span>    VkStencilOp depthFailOp;
<span class="line-numbers">31</span>    VkCompareOp compareOp;
<span class="line-numbers">32</span>} VezStencilOpState;
<span class="line-numbers">33</span>
<span class="line-numbers">34</span><span class="keyword">typedef</span> <span class="keyword">struct</span> VezDepthStencilState {
<span class="line-numbers">35</span>    VkBool32 depthTestEnable;
<span class="line-numbers">36</span>    VkBool32 depthWriteEnable;
<span class="line-numbers">37</span>    VkCompareOp depthCompareOp;
<span class="line-numbers">38</span>    VkBool32 depthBoundsTestEnable;
<span class="line-numbers">39</span>    VkBool32 stencilTestEnable;
<span class="line-numbers">40</span>    VkStencilOpState front;
<span class="line-numbers">41</span>    VkStencilOpState back;
<span class="line-numbers">42</span>} VezDepthStencilState;
<span class="line-numbers">43</span>
<span class="line-numbers">44</span><span class="keyword">typedef</span> <span class="keyword">struct</span> VezColorBlendAttachmentState {
<span class="line-numbers">45</span>    VkBool32 blendEnable;
<span class="line-numbers">46</span>    VkBlendFactor srcColorBlendFactor;
<span class="line-numbers">47</span>    VkBlendFactor dstColorBlendFactor;
<span class="line-numbers">48</span>    VkBlendOp colorBlendOp;
<span class="line-numbers">49</span>    VkBlendFactor srcAlphaBlendFactor;
<span class="line-numbers">50</span>    VkBlendFactor dstAlphaBlendFactor;
<span class="line-numbers">51</span>    VkBlendOp alphaBlendOp;
<span class="line-numbers">52</span>    VkColorComponentFlags colorWriteMask;
<span class="line-numbers">53</span>} VezColorBlendAttachmentState;
<span class="line-numbers">54</span>
<span class="line-numbers">55</span><span class="keyword">typedef</span> <span class="keyword">struct</span> VezColorBlendState {
<span class="line-numbers">56</span>    VkBool32 logicOpEnable;
<span class="line-numbers">57</span>    VkLogicOp logicOp;
<span class="line-numbers">58</span>    uint32_t attachmentCount;
<span class="line-numbers">59</span>    <span class="directive">const</span> VkPipelineColorBlendAttachmentState* pAttachments;
<span class="line-numbers">60</span>} VezColorBlendState;</code></pre>
</div>
</div>
<div class="paragraph">
<p>An application is not required to set these, as V-EZ sets default values when an application calls <code>vezBeginCommandBuffer</code>. The following tables list the default values for each state.</p>
</div>
<table class="tableblock frame-all grid-all fit-content">
<caption class="title">VezInputAssemblyState: Default values</caption>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Field name</th>
<th class="tableblock halign-left valign-top">Default value</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">topology</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">primitiveRestartEnable</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_FALSE</em></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><br></p>
</div>
<table class="tableblock frame-all grid-all fit-content">
<caption class="title">VezRasterizationState: Default values</caption>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Field name</th>
<th class="tableblock halign-left valign-top">Default value</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">depthClampEnable</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_FALSE</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">rasterizerDiscardEnable</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_FALSE</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">polygonMode</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_POLYGON_MODE_FILL</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">cullMode</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_CULL_MODE_NONE</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">frontFace</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_FRONT_FACE_COUNTER_CLOCKWISE</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">depthBiasEnable</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_FALSE</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">depthBiasConstantFactor</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>0.0</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">depthBiasClamp</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>1.0</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">depthBiasSlopeFactor</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>1.0</em></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><br></p>
</div>
<table class="tableblock frame-all grid-all fit-content">
<caption class="title">VezMultisampleState: Default values</caption>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Field name</th>
<th class="tableblock halign-left valign-top">Default value</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">rasterizationSamples</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_SAMPLE_COUNT_1_BIT</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">sampleShadingEnable</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_FALSE</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">minSampleShading</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>1.0</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">pSampleMask</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>NULL</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">alphaToCoverageEnable</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_FALSE</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">alphaToOneEnable</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_FALSE</em></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><br></p>
</div>
<table class="tableblock frame-all grid-all fit-content">
<caption class="title">VezDepthStencilState: Default values</caption>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Field name</th>
<th class="tableblock halign-left valign-top">Default value</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">depthTestEnable</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_FALSE</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">depthWriteEnable</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_TRUE</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">depthCompareOp</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_COMPARE_OP_LESS_OR_EQUAL</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">depthBoundsTestEnable</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_FALSE</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">stencilTestEnable</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_FALSE</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">front</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>N/A</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">back</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>N/A</em></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><br></p>
</div>
<table class="tableblock frame-all grid-all fit-content">
<caption class="title">VezColorBlendState: Default values</caption>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Field name</th>
<th class="tableblock halign-left valign-top">Default value</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">logicOpEnable</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_FALSE</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">logicOp</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>VK_LOGIC_OP_SET</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">attachmentCount</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>0</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">pAttachments</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>NULL</em></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><br></p>
</div>
<div class="paragraph">
<p>All state blocks are set together, therefore default values must still be set when the application only needs to set a single field. For example, when enabling backface culling, the polygonMode should still be set. The code listing below demonstrates setting setting the viewport, expected primitive topology and enabling backface culling and depth testing.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span>vezBeginCommandBuffer(commandBuffer, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
<span class="line-numbers"> 2</span>
<span class="line-numbers"> 3</span>VkViewport viewport = { <span class="float">0</span><span class="float">.0f</span>, <span class="float">0</span><span class="float">.0f</span>, width, height, <span class="float">0</span><span class="float">.0f</span>, <span class="float">1</span><span class="float">.0f</span> };
<span class="line-numbers"> 4</span>vezCmdSetViewport(<span class="integer">0</span>, <span class="integer">1</span>, &amp;viewport);
<span class="line-numbers"> 5</span>vezCmdSetViewportState(<span class="integer">1</span>);
<span class="line-numbers"> 6</span>
<span class="line-numbers"> 7</span>VezInputAssemblyState inputAssemblyState = {};
<span class="line-numbers"> 8</span>inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
<span class="line-numbers"> 9</span>inputAssemblyState.primitiveRestartEnable = VK_FALSE;
<span class="line-numbers">10</span>vezCmdSetInputAssemblyState(&amp;inputAssemblyState);
<span class="line-numbers">11</span>
<span class="line-numbers">12</span>VezRasterizationState rasterizationState = {};
<span class="line-numbers">13</span>rasterizationState.polygonMode = VK_POLGYON_MODE_FILL;
<span class="line-numbers">14</span>rasterizationState.cullMode = VK_CULL_MODE_BACK_BIT;
<span class="line-numbers">15</span>rasterizationState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
<span class="line-numbers">16</span>vezCmdSetRasterizationState(&amp;rasterizationState);
<span class="line-numbers">17</span>
<span class="line-numbers">18</span>VezDepthStencilState depthStencilState = {};
<span class="line-numbers">19</span>depthStencilState.depthTestEnable = VK_TRUE;
<span class="line-numbers">20</span>depthStencilState.depthWriteEnable = VK_FALSE;
<span class="line-numbers">21</span>depthStencilState.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
<span class="line-numbers">22</span>vezCmdSetDepthStencilState(&amp;depthStencilState);
<span class="line-numbers">23</span>
<span class="line-numbers">24</span><span class="comment">// Draw commands</span>
<span class="line-numbers">25</span>
<span class="line-numbers">26</span>vezEndCommandBuffer();</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_resource_binding">9.4. Resource Binding</h3>
<div class="paragraph">
<p>In Vulkan descriptor sets are required for binding resources to different bindings for use in a pipeline.  The complexities of descriptor set layouts, descriptor pools and updating descriptor set objects has been abstracted away in V-EZ.  Instead a simplified interface of explicitly binding <em>buffers</em>, <em>bufferViews</em>, and <em>images</em> to set and binding indices during command buffer recording is exposed. These bindings are persistent only with a command buffer, but maintain persistence across pipeline bindings.</p>
</div>
<div class="paragraph">
<p>Each binding function for different resource types requires the set number, binding, and array element index.  The following functions are available for binding each resource type.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="directive">void</span> vezCmdBindBuffer(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range, uint32_t set, uint32_t binding, uint32_t arrayElement)

<span class="directive">void</span> vezCmdBindBufferView(VkBufferView bufferView, uint32_t set, uint32_t binding, uint32_t arrayElement)

<span class="directive">void</span> vezCmdBindImageView(VkImageView imageView, VkSampler sampler, uint32_t set, uint32_t binding, uint32_t arrayElement);

<span class="directive">void</span> vezCmdBindSampler(VkSampler sampler, uint32_t set, uint32_t binding, uint32_t arrayElement);</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The preprocessor macro <code>VK_WHOLE_SIZE</code> may be passed to the <code>range</code> parameter of <code>vezCmdBindBuffer</code> when an application desires to bind the entire buffer and not a sub range.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p><code>vkCmdBindImageView</code> allows an application to specify a sampler alongside the image view.  When sampler is VK_NULL_HANDLE, the binding represents a <em>sampled image</em> or <strong>texture2D</strong> in GLSL.  When sample is not VK_NULL_HANDLE, it represents a <em>combined image sampler</em> or 'sampler2D' in GLSL.  See <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#descriptorsets-types">13.1.3 Sampled Image</a> in the Vulkan spec for more details.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_render_passes">10. Render Passes</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Render passes in Vulkan are used to encapsulate all draw commands.  No draw command may occur outside of a render pass.  Render passes allow an application to define a sequence of dependent stages within an application&#8217;s rendering pipeline that should be synchronized and may access the same framebuffer attachments. Desktop applications may not benefit as much from this feature as mobile applications, however use of render passes is still encouraged as AMD&#8217;s driver can make specific optimizations under many circumstances.</p>
</div>
<div class="paragraph">
<p>Render passes are greatly simplified in V-EZ.  Applications are no longer required to:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Explicitly create render pass objects</p>
</li>
<li>
<p>Manage render pass compatibility with pipelines and framebuffers</p>
</li>
<li>
<p>Define attachment image layouts and transitions</p>
</li>
<li>
<p>Define input attachments</p>
</li>
<li>
<p>Define all subpasses up front</p>
</li>
<li>
<p>Define subpass dependencies</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>These tasks are handled automatically by V-EZ, and in some cases inferred from the SPIR-V of bound pipeline shader stages.  To learn more about render passes and their use cases, please see the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#renderpass">Vulkan spec</a>.</p>
</div>
<div class="sect2">
<h3 id="_begin_a_render_pass">10.1. Begin A Render Pass</h3>
<div class="paragraph">
<p>To begin a render pass, an application may call <code>vkCmdBeginRenderPass</code>.  The <code>VezRenderPassBeginInfo</code> structure requires a target framebuffer to be specified, an array of <code>VezAttachmentReference</code> structures which define load operations, store operations and clear values. The code listing below demonstrates beginning a render pass with two attachments, namely a single color attachment and a depth stencil attachment.  Both attachments are cleared and any values written by the fragment shader stage stored.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span><span class="comment">// Clear the framebuffer's color and depth attachments (set clear color to red).</span>
<span class="line-numbers"> 2</span><span class="comment">// Always store the fragment stage results.</span>
<span class="line-numbers"> 3</span>std::array&lt;VezAttachmentReference, <span class="integer">2</span>&gt; attachmentReferences = {};
<span class="line-numbers"> 4</span>attachmentReferences[<span class="integer">0</span>].clearValue.color = { <span class="float">0</span><span class="float">.3f</span>, <span class="float">0</span><span class="float">.3f</span>, <span class="float">0</span><span class="float">.3f</span>, <span class="float">0</span><span class="float">.0f</span> };
<span class="line-numbers"> 5</span>attachmentReferences[<span class="integer">0</span>].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
<span class="line-numbers"> 6</span>attachmentReferences[<span class="integer">0</span>].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
<span class="line-numbers"> 7</span>attachmentReferences[<span class="integer">1</span>].clearValue.depthStencil.depth = <span class="float">1</span><span class="float">.0f</span>;
<span class="line-numbers"> 8</span>attachmentReferences[<span class="integer">1</span>].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
<span class="line-numbers"> 9</span>attachmentReferences[<span class="integer">1</span>].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
<span class="line-numbers">10</span>
<span class="line-numbers">11</span><span class="comment">// Begin a render pass.</span>
<span class="line-numbers">12</span>VezRenderPassBeginInfo beginInfo = {};
<span class="line-numbers">13</span>beginInfo.framebuffer = framebuffer;
<span class="line-numbers">14</span>beginInfo.attachmentCount = <span class="keyword">static_cast</span>&lt;uint32_t&gt;(attachmentReferences.size());
<span class="line-numbers">15</span>beginInfo.pAttachments = attachmentReferences.data();
<span class="line-numbers">16</span>vezCmdBeginRenderPass(commandBuffer, &amp;beginInfo);</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_next_subpass">10.2. Next Subpass</h3>
<div class="paragraph">
<p>By default, calling vkCmdBeginRenderPass starts the first subpass.  To transition to a proceeding one, an application may call <code>vezCmdNextSubpass</code>.  No parameters are required except the command buffer the call is being recorded to.</p>
</div>
<div class="paragraph">
<p>As previously stated, V-EZ determines which framebuffer attachments are written to within each subpass based on the pipeline objects that are bound and draw calls made.</p>
</div>
</div>
<div class="sect2">
<h3 id="_end_a_render_pass">10.3. End A Render Pass</h3>
<div class="paragraph">
<p>To end a render pass, call <code>vezCmdEndRenderPass</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_input_attachments">10.4. Input Attachments</h3>
<div class="paragraph">
<p>Vulkan allows framebuffer attachments to be used as inputs or outputs within a render pass.  One subpass may write to a color attachment while a proceeding subpass may read from it.  V-EZ infers this information from the bound pipeline shader stages, specifically the GLSL <code>subpassInput</code> uniform type (see 13.1.11. Input Attachment in the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html">Vulkan spec</a> for more details.  In the code snippet below, the first subpass outputs to two attachments for color and surface normals.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span><span class="preprocessor">#version</span> <span class="integer">450</span>
<span class="line-numbers"> 2</span><span class="preprocessor">#extension</span> GL_ARB_separate_shader_objects : enable
<span class="line-numbers"> 3</span>
<span class="line-numbers"> 4</span>layout(location = <span class="integer">0</span>) in VS_OUT
<span class="line-numbers"> 5</span>{
<span class="line-numbers"> 6</span>    vec3 worldNormal;
<span class="line-numbers"> 7</span>} ps_in;
<span class="line-numbers"> 8</span>
<span class="line-numbers"> 9</span>layout(location = <span class="integer">0</span>) out vec4 albedo;
<span class="line-numbers">10</span>layout(location = <span class="integer">1</span>) out vec4 normals;
<span class="line-numbers">11</span>
<span class="line-numbers">12</span><span class="directive">void</span> main()
<span class="line-numbers">13</span>{
<span class="line-numbers">14</span>    albedo = ...
<span class="line-numbers">15</span>    normals = ps_in.worldNormal;
<span class="line-numbers">16</span>}</code></pre>
</div>
</div>
<div class="paragraph">
<p>In the next subpass, the framebuffer attachment storing the normals, index 1, is bound as an input attachment within the shader.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span><span class="preprocessor">#version</span> <span class="integer">450</span>
<span class="line-numbers"> 2</span><span class="preprocessor">#extension</span> GL_ARB_separate_shader_objects : enable
<span class="line-numbers"> 3</span>
<span class="line-numbers"> 4</span>layout(input_attachment_index = <span class="integer">1</span>, set = <span class="integer">0</span>, binding = <span class="integer">0</span>) uniform subpassInput normals;
<span class="line-numbers"> 5</span>layout(location = <span class="integer">0</span>) out vec4 finalColor;
<span class="line-numbers"> 6</span>
<span class="line-numbers"> 7</span><span class="directive">void</span> main()
<span class="line-numbers"> 8</span>{
<span class="line-numbers"> 9</span>    vec4 normal = subpassLoad(normals);
<span class="line-numbers">10</span>    finalColor = ...
<span class="line-numbers">11</span>}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>input_attachment_index</code> value used in the shader should match the index of the attachment when the framebuffer was created.  In V-EZ these must be absolute indices.  The same applies for the <code>location</code> index for output attachments.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_updating_memory">11. Updating Memory</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Since V-EZ does not explicitly expose underlying memory handles as in Vulkan, applications update buffer and image data using the <code>VkBuffer</code> and <code>VkImage</code> handles directly.</p>
</div>
<div class="sect2">
<h3 id="_map_and_unmap">11.1. Map and Unmap</h3>
<div class="paragraph">
<p>V-EZ exposes map and unmap operations for <code>VkBuffer</code> handles only.  An application must ensure that the target <code>VkBuffer</code> handle was created with the correct <code>VezMemoryFlags</code>.  The <strong>VEZ_MEMORY_GPU_ONLY</strong> is the only enumeration value which cannot be mapped.</p>
</div>
<div class="paragraph">
<p>To map and unmap a buffer, an application calls <code>VezMapBuffer</code> and <code>vezUnmapBuffer</code>.  Care must be taken to call <code>vezFlushMappedBufferRanges</code> to guarantee writes by the host are made available to the device.  The behavior remains nearly indentical to Vulkan&#8217;s <code>vkMapMemory</code> function.  See the <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#memory-device-hostaccess">Vulkan spec</a> for more details.</p>
</div>
</div>
<div class="sect2">
<h3 id="_utility_functions">11.2. Utility Functions</h3>
<div class="paragraph">
<p>V-EZ simplifies host to device data transfers by providing two utility functions. Both are synchronous function calls on the host and block the calling thread until completion.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="c++"><span class="line-numbers"> 1</span>VkResult vezBufferSubData(VkDevice device, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, <span class="directive">const</span> <span class="directive">void</span>* pData);
<span class="line-numbers"> 2</span>
<span class="line-numbers"> 3</span><span class="keyword">typedef</span> <span class="keyword">struct</span> VezImageSubDataInfo {
<span class="line-numbers"> 4</span>    uint32_t dataRowLength;
<span class="line-numbers"> 5</span>    uint32_t dataImageHeight;
<span class="line-numbers"> 6</span>    VezImageSubresourceLayers imageSubresource;
<span class="line-numbers"> 7</span>    VkOffset3D imageOffset;
<span class="line-numbers"> 8</span>    VkExtent3D imageExtent;
<span class="line-numbers"> 9</span>} VezImageSubDataInfo;
<span class="line-numbers">10</span>
<span class="line-numbers">11</span>VkResult vezImageSubData(VkDevice device, VkImage image, <span class="directive">const</span> VezImageSubDataInfo* pSubDataInfo, <span class="directive">const</span> <span class="directive">void</span>* pData);</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_glsl_guide">12. GLSL Guide</h2>
<div class="sectionbody">
<div class="paragraph">
<p><em>TODO</em></p>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2018-08-30 20:57:17 Central Daylight Time
</div>
</div>
</body>
</html>